<!DOCTYPE html>
<html lang="zh-CN">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>拖拽低代码编辑器</title>
  <!-- 
  拖拽事件是HTML5中引入的一种交互方式，允许用户通过鼠标拖动元素来进行操作。以下是关于拖拽事件的总结，包括常用事件及其说明：

  ### 拖拽事件概述

  拖拽事件主要包括以下几个阶段：

  1. 拖动开始（`dragstart`）
  2. 拖动过程（`drag`）
  3. 拖动结束（`dragend`）
  4. 拖动进入（`dragenter`）
  5. 拖动离开（`dragleave`）
  6. 拖动悬停（`dragover`）
  7. 放置（`drop`）

  ### 事件说明

  1. `dragstart`
    - 当用户开始拖动一个元素时触发。
    - 可以在此事件中设置拖动的数据（例如：`event.dataTransfer.setData`）。

  2. `drag`
    - 在拖动过程中不断触发，通常用于更新拖动元素的状态或样式。

  3. `dragend`
    - 当拖动操作结束时触发，不论是放置成功还是取消。
    - 可以在此事件中清理状态或样式。

  4. `dragenter`
    - 当拖动的元素进入一个有效的放置目标时触发。
    - 可以在此事件中改变目标元素的样式，表示可以放置。

  5. `dragleave`
    - 当拖动的元素离开一个有效的放置目标时触发。
    - 可以在此事件中恢复目标元素的样式。

  6. `dragover`
    - 当拖动的元素在有效的放置目标上移动时触发。
    - 必须调用`event.preventDefault()`以允许放置操作。

  7. `drop`
    - 当拖动的元素在放置目标上放下时触发。
    - 可以在此事件中处理放置的数据（例如：`event.dataTransfer.getData`）。

  8. `draggable`
    - 用于设置元素是否可拖动，是一个布尔属性。

  ### 使用示例

  以下是一个简单的拖拽事件处理示例：

  ```javascript
  const draggable = document.getElementById('draggable');
  const dropzone = document.getElementById('dropzone');

  draggable.addEventListener('dragstart', (event) => {
      event.dataTransfer.setData('text/plain', event.target.id);
  });

  dropzone.addEventListener('dragover', (event) => {
      event.preventDefault(); // 允许放置
  });

  dropzone.addEventListener('drop', (event) => {
      event.preventDefault();
      const data = event.dataTransfer.getData('text/plain');
      const draggedElement = document.getElementById(data);
      dropzone.appendChild(draggedElement); // 将元素放置到目标
  });
  ```

  ### 注意事项

  - 拖拽事件在不同浏览器中的支持情况可能有所不同，确保进行兼容性测试。
  - 使用拖拽时，注意用户体验，确保拖拽操作流畅且直观。

  通过以上总结和示例，你可以更好地理解和使用拖拽事件来实现交互功能。
  -->
  <style>
    body {
      font-family: Arial, sans-serif;
      margin: 0;
      padding: 20px;
    }

    .container {
      display: flex;
    }

    .palette {
      width: 200px;
      margin-right: 20px;
    }

    .draggable {
      padding: 10px;
      margin: 5px;
      background-color: #f0f0f0;
      border: 1px solid #ccc;
      cursor: pointer;
    }

    .editor {
      flex-grow: 1;
      height: 400px;
      border: 2px dashed #ccc;
      display: flex;
      align-items: center;
      justify-content: center;
    }
  </style>
</head>

<body>
  <div class="container">
    <div class="palette">
      <div class="draggable" draggable="true">文本框</div>
      <div class="draggable" draggable="true">按钮</div>
      <div class="draggable" draggable="true">图片</div>
    </div>
    <div class="editor" id="editor">
      <h2>拖拽到这里</h2>
    </div>
  </div>
  <script>
    const draggables = document.querySelectorAll('.draggable');
    const editor = document.getElementById('editor');

    draggables.forEach(draggable => {
      draggable.addEventListener('dragstart', () => {
        draggable.classList.add('dragging');
      });

      draggable.addEventListener('dragend', () => {
        draggable.classList.remove('dragging');
      });
    });

    editor.addEventListener('dragover', (e) => {
      e.preventDefault(); // 防止默认行为，以便可以放置
    });

    editor.addEventListener('drop', (e) => {
      e.preventDefault();
      const draggingElement = document.querySelector('.dragging');
      const newElement = document.createElement('div');

      if (draggingElement.innerText === '文本框') {
        newElement.innerHTML = '<input type="text" placeholder="文本框" />';
      } else if (draggingElement.innerText === '按钮') {
        newElement.innerHTML = '<button>按钮</button>';
      } else if (draggingElement.innerText === '图片') {
        newElement.innerHTML = '<img src="https://via.placeholder.com/150" alt="示例图片" />';
      }

      newElement.classList.add('dropped-element');
      editor.appendChild(newElement);
    });
  </script>
</body>

</html>